/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.amse.grigory.dchess.io;

import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import org.amse.grigory.dchess.dchess.DChess;
import org.amse.grigory.dchess.kernel.*;
import org.amse.grigory.dchess.rules.*;
import org.w3c.dom.*;

/**
 *
 * @author grigory
 */
public class XMLReader implements IReader {

    private String myFile;
    private Document myDom;
    private HashMap<String, Figure> myFigures;
    private int myL = -1;
    private static ClassLoader ourDClass = DChess.class.getClassLoader();

    public XMLReader(String name) {
        myFile = name;
    }

    public void close() throws IOException {
    }

    public void open() throws Exception {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        myDom = null;
        DocumentBuilder db = dbf.newDocumentBuilder();
        myDom = db.parse(ourDClass.getResource(myFile).openStream());
    }

    public Rules createRules() throws NullPointerException {
        Rules rules = null;
        myFigures = new HashMap<String, Figure>();
        Node node = myDom.getChildNodes().item(0);
        int length = node.getChildNodes().getLength();
        for (int i = 0; i < length; i++) {
            if (node.getChildNodes().item(i).getNodeType() == myDom.ELEMENT_NODE) {
                if (node.getChildNodes().item(i).getNodeName().equals("rules")) {
                    Node tnode = node.getChildNodes().item(i);
                    String s = tnode.getAttributes().item(0).getNodeValue();
                    if (s.equals("BasicChessRules")) {
                        rules = new BasicChessRules();
                    }
                    if (s.equals("ChessRules")) {
                        rules = new ChessRules();
                    }
                }
                if (node.getChildNodes().item(i).getNodeName().equals("desk")) {
                    createDesk(rules, node.getChildNodes().item(i));
                }
                if (node.getChildNodes().item(i).getNodeName().equals("figures")) {
                    createFigures(node.getChildNodes().item(i));
                }
                if (node.getChildNodes().item(i).getNodeName().equals("position")) {
                    createPosition(rules, node.getChildNodes().item(i));
                }
            }
        }
        rules.setFigures(myFigures);
        return rules;
    }

    private void createDesk(Rules rules, Node node) {
        int h = 0, w = 0;
        int length = node.getAttributes().getLength();
        for (int i = 0; i < length; i++) {
            if (node.getAttributes().item(i).getNodeName().equals("height")) {
                h = Integer.valueOf(node.getAttributes().item(i).getNodeValue());
            }
            if (node.getAttributes().item(i).getNodeName().equals("width")) {
                w = Integer.valueOf(node.getAttributes().item(i).getNodeValue());
            }
        }
        rules.setHeight(h);
        rules.setWidth(w);
        myL = Math.max(h, w);
        length = node.getChildNodes().getLength();
        for (int i = 0; i < length; i++) {
            if (node.getChildNodes().item(i).getNodeType() == myDom.ELEMENT_NODE) {
                if (node.getChildNodes().item(i).getNodeName().equals("illegal")) {
                    Node temp = node.getChildNodes().item(i);
                    String s = temp.getChildNodes().item(0).getNodeValue();
                    Scanner sc = new Scanner(s);
                    int x = Integer.valueOf(sc.next());
                    int y = Integer.valueOf(sc.next());
                    x--;
                    y--;
                    rules.addIllegalSquare(x, y);
                }
            }
        }
    }

    private void createFigures(Node node) {
        int length = node.getChildNodes().getLength();
        for (int i = 0; i < length; i++) {
            if ((node.getChildNodes().item(i).getNodeType() == node.ELEMENT_NODE) && (node.getChildNodes().item(i).getNodeName().equals("figure"))) {
                Figure temp = createFigure(node.getChildNodes().item(i));
                myFigures.put(temp.getName(), temp);
            }
        }
    }

    private Figure createFigure(Node node) {
        Figure temp = new Figure();
        if (node.getAttributes().item(0).getNodeName().equals("name")) {
            temp.setName(node.getAttributes().item(0).getNodeValue());
        }
        int length = node.getChildNodes().getLength();
        for (int i = 0; i < length; i++) {
            if (node.getChildNodes().item(i).getNodeType() == node.ELEMENT_NODE) {
                String s = node.getChildNodes().item(i).getNodeName();
                if (s.equals("move")) {
                    addMoves(temp, node.getChildNodes().item(i));
                }
                if (s.equals("eat")) {
                    addEates(temp, node.getChildNodes().item(i));
                }
                if (s.equals("transform")) {
                    addTransform(temp, node.getChildNodes().item(i));
                }
            }
        }
        return temp;
    }

    private void addTransform(Figure figure, Node node) {
        int line = -1;
        String s = null;
        int n = node.getAttributes().getLength();
        for (int i = 0; i < n; i++) {
            Node tnode = node.getAttributes().item(i);
            if (tnode.getNodeName().equals("line")) {
                line = Integer.valueOf(tnode.getNodeValue());
            }
            if (tnode.getNodeName().equals("figure")) {
                s = tnode.getNodeValue();
            }
        }
        if (s != null) {
            figure.addTransform(line, s);
        }
    }

    private void addMoves(Figure figure, Node node) {
        char type = Moves.NOT_A_MOVE;
        if (node.getAttributes().item(0).getNodeName().equals("type")) {
            String s = node.getAttributes().item(0).getNodeValue();
            if (s.equals("slide")) {
                type = Moves.MOVE_SLIDE;
            }
            if (s.equals("fslide")) {
                type = Moves.MOVE_FSLIDE;
            }
            if (s.equals("jump")) {
                type = Moves.MOVE_JUMP;
            }
            if (s.equals("fjump")) {
                type = Moves.MOVE_FJUMP;
            }
            if (s.equals("special")) {
                type = Moves.MOVE_SPECIAL;
            }
        }
        int x, y;
        String s = node.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
        Scanner sc = new Scanner(s);
        x = Integer.valueOf(sc.next());
        y = Integer.valueOf(sc.next());
        if (node.getChildNodes().item(0).getNodeName().equals("to")) {
            figure.addMove(x, y, type);
        }
        if (node.getChildNodes().item(0).getNodeName().equals("vect")) {
            int tx = 0;
            int ty = 0;
            for (int i = 0; i < myL; i++) {
                tx += x;
                ty += y;
                figure.addMove(tx, ty, type);
            }

        }
    }

    private void addEates(Figure figure, Node node) {
        char type = Moves.NOT_A_MOVE;
        if (node.getAttributes().item(0).getNodeName().equals("type")) {
            String s = node.getAttributes().item(0).getNodeValue();
            if (s.equals("slide")) {
                type = Moves.MOVE_SLIDE;
            }
            if (s.equals("fslide")) {
                type = Moves.MOVE_FSLIDE;
            }
            if (s.equals("jump")) {
                type = Moves.MOVE_JUMP;
            }
            if (s.equals("fjump")) {
                type = Moves.MOVE_FJUMP;
            }
        }
        int x, y;
        String s = node.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
        Scanner sc = new Scanner(s);
        x = Integer.valueOf(sc.next());
        y = Integer.valueOf(sc.next());
        if (node.getChildNodes().item(0).getNodeName().equals("to")) {
            figure.addEat(x, y, type);
        }
        if (node.getChildNodes().item(0).getNodeName().equals("vect")) {
            int tx = 0;
            int ty = 0;
            for (int i = 0; i < myL; i++) {
                tx += x;
                ty += y;
                figure.addEat(tx, ty, type);
            }

        }
    }

    private void createPosition(Rules rules, Node node) {
        int length = node.getChildNodes().getLength();
        for (int i = 0; i < length; i++) {
            if (node.getChildNodes().item(i).getNodeType() == node.ELEMENT_NODE) {
                if (node.getChildNodes().item(i).getNodeName().equals("figure")) {
                    Node temp = node.getChildNodes().item(i);
                    String color = temp.getAttributes().item(0).getNodeValue();
                    String name = temp.getAttributes().item(1).getNodeValue();
                    String s = temp.getChildNodes().item(0).getNodeValue();
                    Scanner sc = new Scanner(s);
                    int x, y;
                    x = Integer.valueOf(sc.next());
                    y = Integer.valueOf(sc.next());
                    Figure tmp = myFigures.get(name).clone();
                    tmp.setX(x);
                    tmp.setY(y);
                    if (color.equals("white")) {
                        tmp.setColor(Figure.COLOR_WHITE);
                        rules.addWhite(tmp);
                    }
                    if (color.equals("black")) {
                        tmp.setColor(Figure.COLOR_BLACK);
                        rules.addBlack(tmp);
                    }
                }
            }
        }
    }

    public String getFileName() {
        return myFile;
    }

    public void setFileName(String name) {
        myFile = name;
    }
}
